package com.zoro.barn.commons.db.autopage;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zoro.barn.commons.foundation.web.FeignResponseHandleException;
import com.zoro.barn.commons.foundation.web.FeignResponseHandler;
import com.zoro.barn.commons.foundation.web.PageResultInfoInterface;
import com.zoro.barn.commons.tools.json.JsonUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * @author zhaoxingwu
 */
public class PagingFeignResponseHandler implements FeignResponseHandler {

    private final String currentKey;
    private final String totalKey;

    public PagingFeignResponseHandler(String currentKey, String totalKey) {
        this.currentKey = currentKey;
        this.totalKey = totalKey;
    }

    @Override
    public Object handle(Type type, Object data, String responseJson) throws FeignResponseHandleException {

        if (!(data instanceof Collection<?>)) {
            return data;
        }

        if (canHandle(type)) {
            // 只处理返回值类型是  PageInfoInterface 的实现类的带有泛型的声明和不带有泛型的声明
            try {
                ObjectNode objectNode = JsonUtil.readJsonObject(responseJson);
                int current = JsonUtil.getInteger(objectNode, currentKey, 0);
                long count = JsonUtil.getLong(objectNode, totalKey, 0);
                return new PageList<>((Collection<?>)data, current, count);

            } catch (Exception e) {
                throw new FeignResponseHandleException("解析分页数据出错", e);
            }
        } else {
            return data;
        }
    }

    /**
     * 验证是否可以解析 只处理返回值类型是  PageInfoInterface 的实现类的带有泛型的声明和不带有泛型的声明
     * @param type 返回值类型
     * @return true or false
     */
    private boolean canHandle(Type type) {

        // 返回值类型是 PageInfoInterface 的实现类，且没有泛型声明
        if (type instanceof Class<?> && PageResultInfoInterface.class.isAssignableFrom((Class<?>) type)) {
            return true;
        }

        // 返回值类型是 PageInfoInterface 的实现类， 且有泛型声明
        return type instanceof ParameterizedType &&
                ((ParameterizedType) type).getRawType() instanceof Class &&
                PageResultInfoInterface.class.isAssignableFrom((Class<?>) ((ParameterizedType) type).getRawType());
    }
}
